package my.learnDB.tools;

import my.learnDB.tools.resultHandler.impl.ResultListHandlerImpl;

import javax.sql.DataSource;
import java.sql.*;
import java.util.List;

public class ABDBHelper<T> {

    private Class<T> tClass;
    private DataSource dataSource;


    public ABDBHelper(DataSource dataSource, Class<T> tClass) {
        this.tClass = tClass;
        this.dataSource = dataSource;
    }

    /**
     * 执行增删改的方法
     * return 影响的行数
     */
    public int update(String sql, Object... params) throws SQLException {

        Connection conn = dataSource.getConnection();
        PreparedStatement preparedStatement = null;

        try {
            preparedStatement = getPreparedStatement(conn, sql, params);

            return preparedStatement.executeUpdate();

        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            release(conn, preparedStatement, null);
        }
    }


    public T getOneResult(String sql, Object... params) throws SQLException {


        return getResult(sql, params).get(0);
    }

    public List<T> getListResult(String sql, Object... params) throws SQLException {
        return getResult(sql, params);
    }


    private List<T> getResult(String sql, Object... params) throws SQLException {

        Connection conn = dataSource.getConnection();
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        try {
            preparedStatement = getPreparedStatement(conn, sql, params);

            resultSet = preparedStatement.executeQuery();

            System.out.println(resultSet);


            return new ResultListHandlerImpl<T>(tClass).listHandle(resultSet);

        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            release(conn, preparedStatement, resultSet);
        }
    }

    // 创建 PreparedStatement，整合 ？
    private PreparedStatement getPreparedStatement(Connection conn, String sql, Object... params) throws SQLException {

        PreparedStatement preparedStatement = conn.prepareStatement(sql);

        // 得到SQL中的参数信息
        ParameterMetaData parameterMetaData = preparedStatement.getParameterMetaData();

        // 得到 ？ 的个数
        int parameterCount = parameterMetaData.getParameterCount();

        if (parameterCount > 0) {
            if (params == null) {
                throw new NullPointerException("没有sql语句执行必须的参数");
            }
            if (params.length != parameterCount) {
                throw new RuntimeException("传入的参数个数和语句所需的参数个数不一致，语句无法执行");
            }
        }
        //5.给sql语句的参数赋值
        for (int i = 0; i < parameterCount; i++) {
            preparedStatement.setObject(i + 1, params[i]);
        }
        return preparedStatement;
    }



    private void release(Connection conn, PreparedStatement preparedStatement, ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        if (preparedStatement != null) {
            try {
                preparedStatement.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        if (conn != null) {
            try {
                conn.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
